Flurry = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "AceDebug-2.0", "Metrognome-2.0")
--local AceOO = AceLibrary("AceOO-2.0")
local dewdrop = AceLibrary("Dewdrop-2.0")
local tablet = AceLibrary("Tablet-2.0")
local g = AceLibrary("Gratuity-2.0")

local vars = {
	["version"] = 0.2,
	["MH"] = {
		["base"] = 0.00,
		["current"] = 0.00,
	},
	["OH"] = {
		["base"] = 0.00,
		["current"] = 0.00,
	},
	["mph"] = 100,
	["timer"] = {},
	["AP"] = 0,
	["totaltime"] = {
		["last"] = 0,
		["total"] = 0,
	},
	["avgspeed"] = {
		["last"] = 100,
		["total"] = 100,
	},
}

Flurry:RegisterDB("FlurryDB", "FlurryDBPC")
Flurry:RegisterDefaults("profile", {
	["locked"] = false,
	["fontsize"] = 14,
	["frame"] = {
		["width"] = 150,
		["height"] = 30,
	},
	["color"] = {
		["background"] = {
			["r"] = 0.5,
			["g"] = 0.5,
			["b"] = 0.5,
			["a"] = 1,
		},
		["border"] = {
			["r"] = 0.5,
			["g"] = 0.5,
			["b"] = 0.5,
			["a"] = 1,
		},
		["ap"] = {
			["r"] = 1,
			["g"] = 0,
			["b"] = 0,
			["a"] = 1,
		},
		["mph"] = {
			["r"] = 0,
			["g"] = 1,
			["b"] = 0,
			["a"] = 1,
		},
		["speed"] = {
			["r"] = 0,
			["g"] = 1,
			["b"] = 0,
			["a"] = 1,
		},
	},
} )

function Flurry:OnInitialize()
	--self:SetDebugging(true)
	
	self.options = { 
	    type="group",
	    args = {
			color = {
				name = "Colors", type = "group",
	            desc = "Set the colors of various things",
	            args = {
	                background = {
	                    name = "Background", type = 'color',
	                    desc = "Change the Background Color",
	                    get = function()
	                        local bc = self.db.profile.color.background
							return bc.r, bc.g, bc.b, bc.a
						end,
						set = function(r, g, b, a)
							self:UpdateBackgroundColor(r,g,b,a)
						end,
						hasAlpha = true,
						order = 1,
					},
					mph = {
						name = "Speed", type = 'color',
						desc = "Change the Speed Text Color",
						get = function()
							local tc = self.db.profile.color.mph
							return tc.r, tc.g, tc.b, tc.a
						end,
						set = function(r, g, b, a)
							self:UpdateMPHColor(r,g,b,a)
						end,
						hasAlpha = true,
						order = 2,
					},
					ap = {
						name = "Attack Power", type = 'color',
						desc = "Change the Attack Power Text Color",
						get = function()
							local tc = self.db.profile.color.ap
							return tc.r, tc.g, tc.b, tc.a
						end,
						set = function(r, g, b, a)
							self:UpdateAPColor(r,g,b,a)
						end,
						hasAlpha = true,
						order = 2,
					},
					border = {
						name = "Border", type = 'color',
						desc = "Set Border Color",
						get = function()
							local boc = self.db.profile.color.border
							return boc.r, boc.g, boc.b, boc.a
						end,
						set = function(r, g, b, a)
							self:UpdateBorderColor(r,g,b,a)
						end,
						hasAlpha = true,
						order = 3,
					},                    
				},
			}, 
			lock = {
				name = "Lock", type = 'toggle',
				desc = "Lock the frame in place",
				get = 	function()
							return self.db.profile.locked
						end,
				set = 	function(v)
						self.db.profile.locked = v
						end,
			},
			fontsize = {
				name = "Font Size", type = 'range',
				desc = "Change the size of the Text",
				get = function()
					return self.db.profile.fontsize
				end,
				set = function(v)
					self.db.profile.fontsize = v
					a = self.mphfs:GetFont()
					self.mphfs:SetFont(a, v)
					self.apfs:SetFont(a,v)
					self.sfs:SetFont(a, v)
				end,
				min = 10,
				max = 30,
				step = 1,
			},
			framewidth = {
				name = "Frame Width", type = 'range',
				desc = "Change the Width of the Frame",
				get = function()
					return self.db.profile.frame.width
				end,
				set = function(v)
					self.db.profile.frame.width = v
					self.frame:SetWidth(v)
				end,
				min = 100,
				max = 200,
				step = 5,
			},
			frameheight = {
				name = "Frame Height", type = 'range',
				desc = "Change the Height of the Frame",
				get = function()
					return self.db.profile.frame.height
				end,
				set = function(v)
					self.db.profile.frame.height = v
					self.frame:SetHeight(v)
				end,
				min = 20,
				max = 50,
				step = 1,
			},
			reset = {
				name = "Reset", type = 'execute',
				desc = "Reset the current timers",
				func = function()
					self:Reset()
				end,
			},
		},
	}

	
	self:Print("version " .. vars.version .. " Loaded")
	self:Debug("Erasing Gratuity Tooltip")
	g:Erase()
	self:Debug("Setting up Frame")
	self:SetupFrame()
	
   -- Called when the addon is loaded
	self:RegisterMetro("Flurry", self.UpdateTimers, 1, self)
	Flurry:RegisterChatCommand({"/flurry"}, self.options)
	dewdrop:Register(self.frame, 'children', self.options)
	self:SetupTablet()
end

function Flurry:OnEnable()
    -- Called when the addon is enabled
	self:Debug("Registering Events")
	--self:RegisterEvent("UNIT_MODEL_CHANGED")
	self:RegisterEvent("UNIT_ATTACK_SPEED")
	self:RegisterEvent("UNIT_ATTACK_POWER")
	self:RegisterEvent("PLAYER_REGEN_DISABLED")
	self:RegisterEvent("PLAYER_REGEN_ENABLED")
	self:Debug("Events Registered")	
	self:Debug("Updating AP from OnEnable()")
	self:UpdateAP()
	self:Debug("Updating Base Speed from OnEnable()")
	self:UNIT_ATTACK_SPEED()
	self.frame:Show()
end

function Flurry:OnDisable()
	self.frame:Hide()
end

function Flurry:SetupFrame()
	self.frame = CreateFrame("Frame", "FlurryFrame", UIParent)
	self.frame:EnableMouse(true)
	self.frame:SetFrameStrata("MEDIUM")
	self.frame:SetMovable(true)
	self.frame:SetWidth(self.db.profile.frame.width)
    self.frame:SetHeight(self.db.profile.frame.height)
    -- Create MPH Font String
    self.mphfs = self.frame:CreateFontString("$parentMPH","ARTWORK","GameFontNormal")
	self.mphfs:SetFont("Fonts\\ARIALN.TTF", self.db.profile.fontsize)
    self.mphfs:SetText(vars.mph .. "%")
    self.mphfs:SetPoint("TOPRIGHT",-5,-5)
    local tc = self.db.profile.color.mph
    self.mphfs:SetTextColor(tc.r,tc.g,tc.b,tc.a)
    self.mphfs:Show()
	-- Create AP Font String
    self.apfs = self.frame:CreateFontString("$parentAP","ARTWORK","GameFontNormal")
	self.apfs:SetFont("Fonts\\ARIALN.TTF", self.db.profile.fontsize)
    self.apfs:SetText(vars.AP)
    self.apfs:SetPoint("TOPLEFT",5,-5)
    local tc = self.db.profile.color.ap
    self.apfs:SetTextColor(tc.r,tc.g,tc.b,tc.a)
    self.apfs:Show()
	-- Create Speed Font String
    self.sfs = self.frame:CreateFontString("$parentAP","ARTWORK","GameFontNormal")
	self.sfs:SetFont("Fonts\\ARIALN.TTF", self.db.profile.fontsize)
    self.sfs:SetText("MH: " .. vars.MH.current .. " OH: ".. vars.OH.current)
    self.sfs:SetPoint("TOP", self.frame, "BOTTOM",0,0)
    local tc = self.db.profile.color.speed
    self.sfs:SetTextColor(tc.r,tc.g,tc.b,tc.a)
    self.sfs:Show()
    -- Backdrop options
    self.frame:SetBackdrop( { 
      bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", 
      edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 16, edgeSize = 16, 
      insets = { left = 5, right = 5, top = 5, bottom = 5 }
    })
    local boc = self.db.profile.color.border
    self.frame:SetBackdropBorderColor(boc.r,boc.g,boc.b,boc.a)
    local bc = self.db.profile.color.background
	self.frame:SetBackdropColor(bc.r,bc.g,bc.b,bc.a)
	self.frame:ClearAllPoints()
	self.frame:SetPoint("CENTER", WorldFrame, "CENTER", 0, 0)
	self.frame:SetScript("OnMouseDown",function()
        if ( arg1 == "LeftButton" ) then
            if not self.db.profile.locked then
				if IsShiftKeyDown() then
					this:StartMoving()
				end
			end
		end
    end)
    self.frame:SetScript("OnMouseUp",function()
        if ( arg1 == "LeftButton" ) then
			this:StopMovingOrSizing()
		end
    end)
    self.frame:SetScript("OnHide",function() this:StopMovingOrSizing() end)
	
    -- Frame cannot be dragged off the screen
    self.frame:SetClampedToScreen(true)
end

function Flurry:OnDisable()
    -- Called when the addon is disabled
end

function Flurry:PLAYER_REGEN_ENABLED()
	self:Debug("Player Regen Enabled")
	self:StopMetro("Flurry")
end

function Flurry:PLAYER_REGEN_DISABLED()
	self:Debug("Player Regen Disabled")
	for k in pairs(vars.timer) do
		self:Debug("Resetting Timer", k)
		vars.timer[k].active.last = 0
		vars.timer[k].average.last = 0
	end
	vars.totaltime.last = 0
	self:StartMetro("Flurry")
end

function Flurry:UNIT_ATTACK_POWER()
	self:Debug("Updating AP from Event UNIT_ATTACK_POWER")
	self:UpdateAP()
end

function Flurry:UNIT_ATTACK_SPEED()
	self:Debug("Updating Base Speeds from Event UNIT_ATTACK_SPEED", vars.MH.base, vars.OH.base)
	
	g:SetInventoryItem("player", 16)
	_,_,vars.MH.base = g:Find("Speed (%S+)", nil, nil, true)
	g:SetInventoryItem("player", 17)
	_,_,vars.OH.base = g:Find("Speed (%S+)", nil, nil, true)
	
	--if not vars.MH.base then vars.MH.base = 2.00 end
	--if not vars.OH.base then vars.OH.base = 0 end
	vars.MH.base = (tonumber(vars.MH.base) or 2.00)
	vars.OH.base = (tonumber(vars.OH.base) or 0.00)
	
	self:Debug("Base Speeds Updated", "MH:", vars.MH.base, "OH:", vars.OH.base)
	self:Debug("Updating Speed from Event UNIT_ATTACK_SPEED")
	
	self:UpdateSpeed()
end

function Flurry:UpdateAP()
	self:Debug("Updating AP", vars.AP)
	local p,b,d=UnitAttackPower("player")
	vars.AP = (p+(b or 0)-(d or 0))
	self:Debug("AP Updated", vars.AP)
	self.apfs:SetText(vars.AP)
end

function Flurry:UpdateSpeed()
	self:Debug("Updating Speed", vars.MH.current, vars.OH.current)
	local m, o = UnitAttackSpeed("player")
	vars.MH.current, vars.OH.current = UnitAttackSpeed("player");
	self:Debug(m, o, type(UnitAttackSpeed("player")))
	self:Debug(vars.MH.current, vars.OH.current)
	if not vars.MH.current then vars.MH.current = 2.00 end
	if not vars.OH.current then vars.OH.current = 0.00 end
	
	vars.MH.current = format("%.2f", vars.MH.current)
	vars.OH.current = format("%.2f", vars.OH.current)
	if not (tonumber(vars.OH.current) > 0) then
		self.sfs:SetText(vars.MH.current)
	else
		self.sfs:SetText("MH: "..vars.MH.current.." OH: "..vars.OH.current)
	end
	
	self:Debug("Speed Updated", vars.MH.current, vars.OH.current)
	self:Debug("Updating MPH", vars.mph)
	self:Debug("Base Vars", vars.MH.base, vars.MH.current, type(vars.MH.base), type(vars.MH.current))

	vars.mph = format("%3d",(vars.MH.base/vars.MH.current)*100)
	
	self:Debug("MPH Updated", vars.mph)
	self.mphfs:SetText(vars.mph .. "%")
	
	self:Debug("Starting current timer", vars.mph)
	if not vars.timer[vars.mph] then 
		vars.timer[vars.mph] = {
			["active"] = {
				["total"] = 0,
				["last"] = 0,
			},
			["average"] = {
				["total"] = 0,
				["last"] = 0,
			},
		}
	end
	
	self:Debug("Current timer started", vars.mph)
	
	--WepInfo(mainSpeed2, offSpeed2);
	--Set_AS_Text(mph .. "%");
end

function Flurry:UpdateTimers()
	self:Debug("Updating...")
	vars.timer[vars.mph].active.total = vars.timer[vars.mph].active.total + 1
	vars.timer[vars.mph].active.last = vars.timer[vars.mph].active.last + 1
	vars.totaltime.total = vars.totaltime.total + 1
	vars.totaltime.last = vars.totaltime.last + 1
	--vars.timer[vars.mph].average.total = format("%.2f",(vars.timer[vars.mph].active.total/vars.totaltime.total)*100)
	--vars.timer[vars.mph].average.last = format("%.2f",(vars.timer[vars.mph].active.last/vars.totaltime.last)*100)
	vars.avgspeed.total = 0
	vars.avgspeed.last = 0
	for k in self:Sorted(vars.timer) do
		vars.timer[k].average.total = format("%.2f",(vars.timer[k].active.total/vars.totaltime.total)*100)
		vars.timer[k].average.last = format("%.2f",(vars.timer[k].active.last/vars.totaltime.last)*100)
		vars.avgspeed.total = vars.avgspeed.total + (k * (vars.timer[k].average.total/100))
		vars.avgspeed.last = vars.avgspeed.last + (k * (vars.timer[k].average.last/100))
	end
	vars.avgspeed.total = format("%d", vars.avgspeed.total)
	vars.avgspeed.last = format("%d", vars.avgspeed.last)
	tablet:Refresh(self.frame)
end

function Flurry:Reset()
	self:Debug("Resetting Vars")
	vars.MH.base = nil
	vars.MH.current = nil
	vars.OH.base = nil
	vars.OH.current = nil
	vars.mph = 100
	vars.totaltime.total = 0
	vars.totaltime.last = 0
	vars.avgspeed.total = 100
	vars.avgspeed.last = 100
	vars.timer = {}
	vars.AP = 0
	self:Debug("Vars reset")	
	self:Debug("Updating AP from Reset()")
	self:UpdateAP()
	self:Debug("Updating Base Speed from Reset()")
	self:UNIT_ATTACK_SPEED()
end

function Flurry:Bug()
	self:Print("Vars array")
	for k,_ in pairs(vars.timer) do
		self:Print(k)
		self:Print(vars.timer[k].on)
		self:Print("AT"..vars.timer[k].active.total)
		self:Print("AL"..vars.timer[k].active.last)
		self:Print("VT"..vars.timer[k].average.total)
		self:Print("VL"..vars.timer[k].average.last)
	end
	self:Print("TT"..vars.totaltime.total)
	self:Print("TL"..vars.totaltime.last)
end

function Flurry:SetupTablet()
    tablet:Register(self.frame, 
	'children', function()
					tablet:SetTitle("Flurry")
				    local cat = tablet:AddCategory(
					'columns', 3
					)
					cat:AddLine(
						'text', "Total",
						'text2', vars.totaltime.total .. " seconds",
						'text3', vars.avgspeed.total .. "% Avg"
					)
					cat:AddLine(
						'text', "Speed",
						'text2', "Time",
						'text3', "% Active"
					)
				    for k in self:Sorted(vars.timer) do
						if (vars.timer[k].active.total > 0) then
							cat:AddLine(
								'text', k.."%",
								'text2', vars.timer[k].active.total,
								'text3', vars.timer[k].average.total
							)
						end
				    end
					cat:AddLine(
						'text', "Last Fight",
						'text2', vars.totaltime.last .. " seconds",
						'text3', vars.avgspeed.last .. "% Avg"
					)
					cat:AddLine(
						'text', "Speed",
						'text2', "Time",
						'text3', "% Active"
					)
				    for k in self:Sorted(vars.timer) do
						if (vars.timer[k].active.last > 0) then
							cat:AddLine(
								'text', k.."%",
								'text2', vars.timer[k].active.last,
								'text3', vars.timer[k].average.last
							)
						end
				    end
				end,
	'point', "BOTTOM",
	'relativePoint', "TOP"
	)
	
end

function Flurry:UpdateBackgroundColor(r, g, b, a)
	local c = self.db.profile.color.background
    c.r, c.g, c.b, c.a = r, g, b, a
	self.frame:SetBackdropColor(r,g,b,a)
end

function Flurry:UpdateBorderColor(r, g, b, a)
	local c = self.db.profile.color.border
    c.r, c.g, c.b, c.a = r, g, b, a
	self.frame:SetBackdropBorderColor(r,g,b,a)
end

function Flurry:UpdateMPHColor(r, g, b, a)
	local c = self.db.profile.color.mph
    c.r, c.g, c.b, c.a = r, g, b, a
	self.mphfs:SetTextColor(r,g,b,a)
end

function Flurry:UpdateAPColor(r, g, b, a)
	local c = self.db.profile.color.ap
    c.r, c.g, c.b, c.a = r, g, b, a
	self.apfs:SetTextColor(r,g,b,a)
end

function Flurry:Sorted(t, f)
	local a = {}
	for n in pairs(t) do table.insert(a, n) end
	table.sort(a, f)
	local i = 0      -- iterator variable
	local iter = function ()   -- iterator function
		i = i + 1
		if a[i] == nil then return nil
		else return a[i], t[a[i]]
		end
	end
	return iter
end
